using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using JlPay.Sdk.Core;
using JlPay.Sdk.Models;

namespace JlPay.Sdk.Services
{
    /// <summary>
    /// 文件上传服务
    /// </summary>
    public class FileService : BaseService
    {
        /// <summary>
        /// 创建文件上传服务
        /// </summary>
        /// <param name="config">配置对象</param>
        public FileService(Config config) : base(config)
        {
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        /// <param name="request">图片上传请求</param>
        /// <returns>文件上传响应</returns>
        public async Task<FileUploadResponse> UploadImageAsync(ImageUploadRequest request)
        {
            return await UploadFileAsync(request);
        }

        /// <summary>
        /// 上传视频
        /// </summary>
        /// <param name="request">视频上传请求</param>
        /// <returns>文件上传响应</returns>
        public async Task<FileUploadResponse> UploadVideoAsync(VideoUploadRequest request)
        {
            return await UploadFileAsync(request);
        }

        /// <summary>
        /// 上传PDF
        /// </summary>
        /// <param name="request">PDF上传请求</param>
        /// <returns>文件上传响应</returns>
        public async Task<FileUploadResponse> UploadPdfAsync(PdfUploadRequest request)
        {
            return await UploadFileAsync(request);
        }

        /// <summary>
        /// 通用文件上传方法
        /// </summary>
        /// <param name="request">文件上传请求</param>
        /// <returns>文件上传响应</returns>
        private async Task<FileUploadResponse> UploadFileAsync(FileUploadRequest request)
        {
            // 构建完整URL
            string url = _config.BaseUrl + request.GetApiUri();
            string uri = request.GetApiUri();

            if (_config.Debug)
            {
                Console.WriteLine($"=== 文件上传请求 ===");
                Console.WriteLine($"请求URL: {url}");
                Console.WriteLine($"文件名: {request.FileName}");
                Console.WriteLine($"文件大小: {request.FileContent?.Length ?? 0} bytes");
            }

            // 创建multipart/form-data内容
            using var formContent = new MultipartFormDataContent();

            // 添加meta字段
            if (!string.IsNullOrEmpty(request.Meta))
            {
                formContent.Add(new StringContent(request.Meta, Encoding.UTF8), "meta");
            }

            // 添加文件字段
            if (request.FileContent != null && !string.IsNullOrEmpty(request.FileName))
            {
                var fileContent = new ByteArrayContent(request.FileContent);
                formContent.Add(fileContent, "file", request.FileName);
            }

            // 使用meta进行签名（而不是整个form body）
            string signBody = request.Meta ?? "{}";
            
            if (_config.Debug)
            {
                Console.WriteLine($"签名内容: {signBody}");
            }

            // 签名
            var (sign, timestamp, nonce) = _signVerifier.Sign("POST", uri, signBody);

            // 准备请求头
            var headers = new Dictionary<string, string>
            {
                ["x-jlpay-appid"] = _config.AppId,
                ["x-jlpay-nonce"] = nonce,
                ["x-jlpay-timestamp"] = timestamp,
                ["x-jlpay-sign-alg"] = "SM3WithSM2WithDer",
                ["x-jlpay-sign"] = sign
            };

            if (_config.Debug)
            {
                Console.WriteLine("请求头:");
                foreach (var header in headers)
                {
                    Console.WriteLine($"  {header.Key}: {header.Value}");
                }
            }

            // 创建HTTP请求
            var httpRequest = new HttpRequest
            {
                Method = "POST",
                Url = url,
                Headers = headers,
                Body = formContent
            };

            // 发送请求
            var httpResponse = await _httpClient.ExecuteAsync(httpRequest);

            if (_config.Debug)
            {
                Console.WriteLine($"响应状态码: {httpResponse.StatusCode}");
                Console.WriteLine($"响应内容: {httpResponse.Body}");
            }

            // 验证响应签名
            if (httpResponse.Headers.TryGetValue("x-jlpay-sign", out var responseSign))
            {
                try
                {
                    _signVerifier.Verify(
                        "POST",
                        uri,
                        httpResponse.Headers.GetValueOrDefault("x-jlpay-timestamp", ""),
                        httpResponse.Headers.GetValueOrDefault("x-jlpay-nonce", ""),
                        httpResponse.Body,
                        responseSign
                    );
                }
                catch (Exception ex)
                {
                    // 响应签名验证失败时给出警告，但继续处理业务响应
                    if (_config.Debug)
                    {
                        Console.WriteLine($"警告: 响应签名验证失败: {ex.Message}");
                        Console.WriteLine("继续处理业务响应以获取具体错误信息...");
                    }
                    // 不抛出异常，继续处理响应
                }
            }

            // 解析响应
            var responseData = JsonSerializer.Deserialize<Dictionary<string, object>>(httpResponse.Body, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
                PropertyNameCaseInsensitive = true
            });

            var response = new FileUploadResponse();
            ParseResponse(responseData!, response);

            return response;
        }

        /// <summary>
        /// 解析响应数据到响应对象
        /// </summary>
        /// <param name="responseData">响应数据</param>
        /// <param name="response">响应对象</param>
        private static void ParseResponse(Dictionary<string, object> responseData, object response)
        {
            // 使用JSON序列化进行对象映射
            var json = JsonSerializer.Serialize(responseData);
            var options = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
                PropertyNameCaseInsensitive = true
            };

            var parsedResponse = JsonSerializer.Deserialize(json, response.GetType(), options);
            if (parsedResponse != null)
            {
                // 复制属性值
                var properties = response.GetType().GetProperties();
                var sourceProperties = parsedResponse.GetType().GetProperties();

                foreach (var property in properties)
                {
                    if (property.CanWrite)
                    {
                        var sourceProperty = Array.Find(sourceProperties, p => p.Name == property.Name);
                        if (sourceProperty != null && sourceProperty.CanRead)
                        {
                            var value = sourceProperty.GetValue(parsedResponse);
                            property.SetValue(response, value);
                        }
                    }
                }
            }
        }
    }
} 